package com.ruoyi.iot.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.ruoyi.iot.channel.translator.impl.TransformCmdServiceImpl;
import com.ruoyi.iot.domain.*;
import com.ruoyi.iot.domain.dto.ProtocolDTO;
import com.ruoyi.iot.domain.vo.*;
import com.ruoyi.iot.domain.vo.enums.EPlatformCmdType;
import com.ruoyi.iot.domain.vo.enums.ESponsor;
import com.ruoyi.iot.domain.vo.exchange.IotWrapperDTO;
import com.ruoyi.iot.domain.vo.plus.IotDevicePlus;
import com.ruoyi.iot.feign.IProtocolRemoteFeign;
import com.ruoyi.iot.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.xmlbeans.impl.util.HexBin;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;

/**
 * 设备Controller
 *
 * @author ruoyi
 * @date 2022-12-27
 */
@RestController
@RequestMapping("/device")
@Slf4j
public class IotDeviceController extends BaseController
{
    /**
     * 设备服务
     */
    @Autowired
    private IotDeviceServiceImpl iotDeviceService;

    /**
     * 产品服务
     */
    @Autowired
    private IotProductServiceImpl productService;

    /**
     * 产品服务
     */
    @Autowired
    private IotCmdServiceImpl iotCmdService;

    /**
     * 产品解释服务
     */
    @Autowired
    private IotCmdExplainServiceImpl iotCmdExplainService;

    /**
     * 项目服务
     */
    @Autowired
    private IotProjectServiceImpl projectService;

    /**
     * 帧服务
     */
    @Autowired
    private IotFrameServiceImpl iotFrameService;

    /**
     * 设备操作
     */
    @Autowired
    private IotDeviceOperationImpl iotDeviceOperation;

    /**
     * 转换服务
     */
    @Autowired
    private TransformCmdServiceImpl transformCmdService;

    /**
     * 协议转换服务
     */
    @Autowired
    private IProtocolRemoteFeign protocolRemoteFeign;


    /**
     * 查询设备列表
     */
    @RequiresPermissions("iot:device:list")
    @GetMapping("/list")
    public DeviceVoInfo list(IotDevice iotDevice) {
        startPage();
        List<IotDevice> list = iotDeviceService.selectIotDeviceList(iotDevice);
        List<IotDevicePlus> plusList = new ArrayList<>();
        for(IotDevice item: list) {
            IotDevicePlus iotDevicePlus = new IotDevicePlus();
            BeanUtils.copyProperties(item,iotDevicePlus);
            String productName = productService.selectIotProductById(item.getProductId()).getName();
            iotDevicePlus.setProductName(productName);
            String projectName = projectService.selectIotProjectById(item.getProjectId()).getName();
            iotDevicePlus.setProjectName(projectName);
            plusList.add(iotDevicePlus);
        }


        DeviceVoInfo rspData = new DeviceVoInfo();
        rspData.setCode(200);
        rspData.setRows(plusList);
        rspData.setProductList(productService.selectIotProductList(new IotProduct()));
        rspData.setFrameList(iotFrameService.selectIotFrameList(new IotFrame()));
        rspData.setProjectList(projectService.selectIotProjectList(new IotProject()));

        rspData.setMsg("查询成功");
        rspData.setTotal((new PageInfo(list)).getTotal());

        log.info("iotList:" + JSON.toJSONString(rspData));
        return rspData;
    }

    /**
     * 查询满足条件的设备列表
     * @param iotDevice
     * @return
     */
    @PostMapping("/query/list")
    public IotWrapperDTO<List<IotDevice>> queryList(@RequestBody IotDevice iotDevice) {

        IotWrapperDTO iotListDTO = new IotWrapperDTO();
        List<IotDevice> list = iotDeviceService.selectIotDeviceList(iotDevice);
        iotListDTO.setData(list);
        return iotListDTO;
    }

    /**
     * 导出设备列表
     */
    @RequiresPermissions("iot:device:export")
    @Log(title = "设备", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, IotDevice iotDevice)
    {
        List<IotDevice> list = iotDeviceService.selectIotDeviceList(iotDevice);
        ExcelUtil<IotDevice> util = new ExcelUtil<IotDevice>(IotDevice.class);
        util.exportExcel(response, list, "设备数据");
    }

    /**
     * 获取设备详细信息
     */
    @RequiresPermissions("iot:device:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(iotDeviceService.selectIotDeviceById(id));
    }


    /**
     * 获取设备详细信息
     */
    @GetMapping(value = "/cmd/explain/{id}")
    public AjaxResult getCmdExplainId(@PathVariable("id") Long id) {
        IotDevice iotDevice = iotDeviceService.selectIotDeviceById(id);


        IotCmd iotCmd = new IotCmd();
        iotCmd.setProductId(iotDevice.getProductId());
        Long sponsor = Long.valueOf(ESponsor.platform.getValue());
        iotCmd.setSponsor(sponsor);

        iotCmd.setCmdType(EPlatformCmdType.CMD.getValue().longValue());

        List<IotCmd>  cmdList = iotCmdService.selectIotCmdList(iotCmd);
        iotCmd.setCmdType(EPlatformCmdType.NOTICE.getValue().longValue());
        List<IotCmd>  noticeList = iotCmdService.selectIotCmdList(iotCmd);
        cmdList.addAll(noticeList);

        DevCmdExplainVo devCmdExplainVo = new DevCmdExplainVo();

        devCmdExplainVo.setDevId(iotDevice.getDevId());
        List<CmdExplainVo> cmdExplainVos = new ArrayList<>();
        if(cmdList.size() == 0) {
            CmdExplainVo cmdExplainVo = new CmdExplainVo();
            cmdExplainVo.setCmdId(-1L);
            cmdExplainVo.setCmdName("请先配置数据包和指令");
            JSONObject json = new JSONObject();
            json.put("error","please config product");
            cmdExplainVo.setCmdJson(json);
            cmdExplainVos.add(cmdExplainVo);
            devCmdExplainVo.setCmdExplainVos(cmdExplainVos);
        }
        for(IotCmd item: cmdList) {
            IotCmdExplain iotCmdExplain = new IotCmdExplain();
            iotCmdExplain.setCmdId(item.getId());
            List<IotCmdExplain> cmdExplains = iotCmdExplainService.selectIotCmdExplainList(iotCmdExplain);
            CmdExplainVo cmdExplainVo = new CmdExplainVo();
            if(cmdExplains.size() == 0) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("tip","no config any productFiled!");
                cmdExplainVo.setCmdJson(jsonObject);
            } else {
               String json =  cmdExplains.get(0).getJson();
               cmdExplainVo.setCmdId(item.getId());
               cmdExplainVo.setCmdName(item.getName());
               cmdExplainVo.setCmdJson(JSON.parseObject(json));
            }
           cmdExplainVos.add(cmdExplainVo);
        }
        devCmdExplainVo.setCmdExplainVos(cmdExplainVos);

        return AjaxResult.success(devCmdExplainVo);
    }


    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");

    /**
     * 设备指令操作 web端走这个接口
     */
    @PostMapping(value = "/cmd/operate")
    public AjaxResult operateCmd(@RequestBody DevCmdVo devCmdVo) {
        String postInfo = String.format("dev:%s,cmd:%s,post:%s",devCmdVo.getDevId(),devCmdVo.getCmdId(),JSON.toJSONString(devCmdVo.getData()));
        Date postDate = new Date();
        UserOperateVO userOperateVO = iotDeviceOperation.produceUserOperate(devCmdVo);

        log.info("date:"+ df.format(postDate) + " post msg:" + postInfo);
        log.info("date:"+ df.format(new Date()) + " rec success:" + userOperateVO.getSuccess() + " msg:" + userOperateVO.getData());

        if(userOperateVO.getSuccess()) {

            return AjaxResult.success(userOperateVO.getMessage(),userOperateVO.getData());
        } else {
            return AjaxResult.error(userOperateVO.getCode(),userOperateVO.getMessage());
        }
    }

    /**
     * 转换协议
     * @param devCmdVo 设备指令
     * @return
     */
    @PostMapping(value = "/cmd/translate")
    public ProtocolDTO  translateProtocol(@RequestBody DevCmdVo devCmdVo) {
         // log.info("devCmdVo:" + JSON.toJSONString(devCmdVo));
          Long cmdId = devCmdVo.getCmdId();
          JSONObject json =  devCmdVo.getData();

          byte[] cmdBuff = transformCmdService.platformTransform(cmdId,json);
          log.info("hex:" + HexBin.bytesToString(cmdBuff));
          ProtocolDTO protocolDTO = new ProtocolDTO();

          protocolDTO.setHexFrame(HexBin.bytesToString(cmdBuff));
          ProtocolDTO rst = protocolRemoteFeign.wrapperProtocol(protocolDTO);
          return rst;
    }







    /**
     * 新增设备
     */
    @RequiresPermissions("iot:device:add")
    @Log(title = "设备", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody IotDevice iotDevice)
    {
        return toAjax(iotDeviceService.insertIotDevice(iotDevice));
    }

    /**
     * 修改设备
     */
    @RequiresPermissions("iot:device:edit")
    @Log(title = "设备", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody IotDevice iotDevice)
    {
        return toAjax(iotDeviceService.updateIotDevice(iotDevice));
    }

    /**
     * 删除设备
     */
    @RequiresPermissions("iot:device:remove")
    @Log(title = "设备", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(iotDeviceService.deleteIotDeviceByIds(ids));
    }


}
